{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##题目一：1. 对连续型特征，可以用哪个函数可视化其分布？（给出你最常用的一个即可），并根据代码运行结果给出示例。\n",
    "\n",
    "说明一：对连续型特征，可使用hist直方图来可视化。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "ename": "KeyError",
     "evalue": "\"['log_MEDV'] not found in axis\"",
     "output_type": "error",
     "traceback": [
      "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[1;31mKeyError\u001B[0m                                  Traceback (most recent call last)",
      "\u001B[1;32m<ipython-input-7-d4a6299e9ffa>\u001B[0m in \u001B[0;36m<module>\u001B[1;34m()\u001B[0m\n\u001B[0;32m     18\u001B[0m \u001B[0my\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mdf\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;34m\"MEDV\"\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m     19\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m---> 20\u001B[1;33m \u001B[0mX\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mdf\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mdrop\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;34m\"MEDV\"\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;34m\"log_MEDV\"\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0maxis\u001B[0m \u001B[1;33m=\u001B[0m \u001B[1;36m1\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m     21\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m     22\u001B[0m \u001B[0mfeat_names\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mX\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mcolumns\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
      "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\pandas\\core\\frame.py\u001B[0m in \u001B[0;36mdrop\u001B[1;34m(self, labels, axis, index, columns, level, inplace, errors)\u001B[0m\n\u001B[0;32m   3695\u001B[0m                                            \u001B[0mindex\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mindex\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mcolumns\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mcolumns\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m   3696\u001B[0m                                            \u001B[0mlevel\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mlevel\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0minplace\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0minplace\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m-> 3697\u001B[1;33m                                            errors=errors)\n\u001B[0m\u001B[0;32m   3698\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m   3699\u001B[0m     @rewrite_axis_style_signature('mapper', [('copy', True),\n",
      "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\pandas\\core\\generic.py\u001B[0m in \u001B[0;36mdrop\u001B[1;34m(self, labels, axis, index, columns, level, inplace, errors)\u001B[0m\n\u001B[0;32m   3109\u001B[0m         \u001B[1;32mfor\u001B[0m \u001B[0maxis\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mlabels\u001B[0m \u001B[1;32min\u001B[0m \u001B[0maxes\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mitems\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m   3110\u001B[0m             \u001B[1;32mif\u001B[0m \u001B[0mlabels\u001B[0m \u001B[1;32mis\u001B[0m \u001B[1;32mnot\u001B[0m \u001B[1;32mNone\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m-> 3111\u001B[1;33m                 \u001B[0mobj\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mobj\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_drop_axis\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mlabels\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0maxis\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mlevel\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mlevel\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0merrors\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0merrors\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m   3112\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m   3113\u001B[0m         \u001B[1;32mif\u001B[0m \u001B[0minplace\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
      "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\pandas\\core\\generic.py\u001B[0m in \u001B[0;36m_drop_axis\u001B[1;34m(self, labels, axis, level, errors)\u001B[0m\n\u001B[0;32m   3141\u001B[0m                 \u001B[0mnew_axis\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0maxis\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mdrop\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mlabels\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mlevel\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mlevel\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0merrors\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0merrors\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m   3142\u001B[0m             \u001B[1;32melse\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m-> 3143\u001B[1;33m                 \u001B[0mnew_axis\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0maxis\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mdrop\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mlabels\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0merrors\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0merrors\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m   3144\u001B[0m             \u001B[0mresult\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mreindex\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m**\u001B[0m\u001B[1;33m{\u001B[0m\u001B[0maxis_name\u001B[0m\u001B[1;33m:\u001B[0m \u001B[0mnew_axis\u001B[0m\u001B[1;33m}\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m   3145\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n",
      "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\pandas\\core\\indexes\\base.py\u001B[0m in \u001B[0;36mdrop\u001B[1;34m(self, labels, errors)\u001B[0m\n\u001B[0;32m   4402\u001B[0m             \u001B[1;32mif\u001B[0m \u001B[0merrors\u001B[0m \u001B[1;33m!=\u001B[0m \u001B[1;34m'ignore'\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m   4403\u001B[0m                 raise KeyError(\n\u001B[1;32m-> 4404\u001B[1;33m                     '{} not found in axis'.format(labels[mask]))\n\u001B[0m\u001B[0;32m   4405\u001B[0m             \u001B[0mindexer\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mindexer\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;33m~\u001B[0m\u001B[0mmask\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m   4406\u001B[0m         \u001B[1;32mreturn\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mdelete\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mindexer\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
      "\u001B[1;31mKeyError\u001B[0m: \"['log_MEDV'] not found in axis\""
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "from sklearn.metrics import r2_score\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "\n",
    "#%matplotlib inline\n",
    "\n",
    "df = pd.read_csv(\"FE_boston_housing.csv\")\n",
    "\n",
    "#df.head()\n",
    "\n",
    "#df.info()\n",
    "\n",
    "y = df[\"MEDV\"]\n",
    "\n",
    "X = df.drop([\"MEDV\", \"log_MEDV\"], axis = 1)\n",
    "\n",
    "feat_names = X.columns\n",
    "\n",
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=33, test_size=0.2)\n",
    "\n",
    "\n",
    "from sklearn.linear_model import LinearRegression\n",
    "\n",
    "lr = LinearRegression()\n",
    "\n",
    "lr.fit(X_train, y_train)\n",
    "\n",
    "y_test_pred_lr = lr.predict(X_test)\n",
    "y_train_pred_lr = lr.predict(X_train)\n",
    "\n",
    "fs = pd.DataFrame({\"columns\":list(feat_names), \"coef\":list(lr.coef_.T)})\n",
    "fs.sort_values(by=['coef'],ascending=False)\n",
    "\n",
    "print ('The r2 score of LinearRegression on test is', r2_score(y_test, y_test_pred_lr))\n",
    "\n",
    "print ('The r2 score of LinearRegression on train is', r2_score(y_train, y_train_pred_lr))\n",
    "\n",
    "f, ax = plt.subplots(figsize=(7, 5))\n",
    "f.tight_layout()\n",
    "ax.hist(y_train - y_train_pred_lr, bins=40, label='Residuals Linear', color='b', alpha=.5)\n",
    "ax.set_title(\"Histogram of Residuals\")\n",
    "ax.legend(loc='best');\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##题目二：对两个连续型特征，可以用哪个函数得到这两个特征之间的相关性？根据代码运行结果，给出示例。\n",
    "\n",
    "说明二：可用相关矩阵来得到两个特征之间的相关性，可用DataFrame的corr()方法先计算出每对特征间的相关矩阵，然后将所得的相关矩阵传给seaborn的heatmap()方法，渲染出一个基于色彩编码的矩阵。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "cols = df.columns\n",
    "\n",
    "data_corr = df.corr()\n",
    "sns.heatmap(data_corr,annot=True)\n",
    "#data_corr.shape\n",
    "\n",
    "data_corr = data_corr.abs()\n",
    "plt.subplots(figsize=(13, 9))\n",
    "sns.heatmap(data_corr,annot=True)\n",
    "\n",
    "sns.heatmap(data_corr, mask=data_corr < 0.5, cbar=False)\n",
    "\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##题目三：如果发现特征之间有较强的相关性，在选择线性回归模型时应该采取什么措施。\n",
    "\n",
    "说明三：相关性较强时，需要给模型添加正则项。当正则项取L2正则，为岭回归；取L1正则，为Lasso 。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "#岭回归／L2正则\n",
    "\n",
    "from sklearn.linear_model import  RidgeCV\n",
    "\n",
    "alphas = [ 0.01, 0.1, 1, 10,100]\n",
    "\n",
    "ridge = RidgeCV(alphas=alphas, store_cv_values=True)\n",
    "\n",
    "ridge.fit(X_train, y_train)\n",
    "\n",
    "y_test_pred_ridge = ridge.predict(X_test)\n",
    "y_train_pred_ridge = ridge.predict(X_train)\n",
    "\n",
    "print ('The r2 score of RidgeCV on test is', r2_score(y_test, y_test_pred_ridge))\n",
    "print ('The r2 score of RidgeCV on train is', r2_score(y_train, y_train_pred_ridge))\n",
    "\n",
    "mse_mean = np.mean(ridge.cv_values_, axis = 0)\n",
    "plt.plot(np.log10(alphas), mse_mean.reshape(len(alphas),1))\n",
    "\n",
    "plt.xlabel('log(alpha)')\n",
    "plt.ylabel('mse')\n",
    "plt.show()\n",
    "\n",
    "print ('alpha is:', ridge.alpha_)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# Lasso／L1正则\n",
    "\n",
    "from sklearn.linear_model import LassoCV\n",
    "\n",
    "lasso = LassoCV()\n",
    "\n",
    "lasso.fit(X_train, y_train)\n",
    "\n",
    "y_test_pred_lasso = lasso.predict(X_test)\n",
    "y_train_pred_lasso = lasso.predict(X_train)\n",
    "\n",
    "print ('The r2 score of LassoCV on test is', r2_score(y_test, y_test_pred_lasso))\n",
    "print ('The r2 score of LassoCV on train is', r2_score(y_train, y_train_pred_lasso))\n",
    "\n",
    "mses = np.mean(lasso.mse_path_, axis = 1)\n",
    "plt.plot(np.log10(lasso.alphas_), mses)\n",
    "\n",
    "plt.xlabel('log(alpha)')\n",
    "plt.ylabel('mse')\n",
    "plt.show()\n",
    "\n",
    "print ('alpha is:', lasso.alpha_)\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##题目四：当采用带正则的模型以及采用随机梯度下降优化算法时，需要对输入（连续型）特征进行去量纲预处理。课程代码给出了用标准化（StandardScaler）的结果，请改成最小最大缩放（MinMaxScaler）去量纲 ，并重新训练最小二乘线性回归、岭回归、和Lasso模型。\n",
    "\n",
    "说明四：程序如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'train' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[1;31mNameError\u001B[0m                                 Traceback (most recent call last)",
      "\u001B[1;32m<ipython-input-8-e974d78b2709>\u001B[0m in \u001B[0;36m<module>\u001B[1;34m()\u001B[0m\n\u001B[0;32m      5\u001B[0m \u001B[0mmn_log_y\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mMinMaxScaler\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m      6\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m----> 7\u001B[1;33m \u001B[0mX\u001B[0m  \u001B[1;33m=\u001B[0m \u001B[0mmn_X\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mfit_transform\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mtrain\u001B[0m\u001B[1;33m[\u001B[0m\u001B[0mfeat_names\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m      8\u001B[0m \u001B[1;31m#y = mn_y.fit_transform(y.reshape(-1, 1))\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m      9\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n",
      "\u001B[1;31mNameError\u001B[0m: name 'train' is not defined"
     ]
    }
   ],
   "source": [
    "from sklearn.preprocessing import MinMaxScaler\n",
    "\n",
    "mn_X = MinMaxScaler()\n",
    "mn_y = MinMaxScaler()\n",
    "mn_log_y = MinMaxScaler()\n",
    "\n",
    "X  = mn_X.fit_transform(X)\n",
    "#y = mn_y.fit_transform(y.reshape(-1, 1))\n",
    "\n",
    "fe_data = pd.DataFrame(data = X, columns = feat_names, index = df.index)\n",
    "fe_data = pd.concat([fe_data], axis = 1, ignore_index=False)\n",
    "\n",
    "fe_data[\"MEDV\"] = y\n",
    "\n",
    "fe_data.to_csv('FE_boston_housing.csv', index=False)\n",
    "\n",
    "df = pd.read_csv(\"FE_boston_housing.csv\")\n",
    "y = df[\"MEDV\"]\n",
    "#X = df.drop([\"MEDV\", \"log_MEDV\"], axis = 1)\n",
    "X = df.drop([\"MEDV\"], axis = 1)\n",
    "feat_names = X.columns\n",
    "\n",
    "from sklearn.model_selection import train_test_split\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=33, test_size=0.2)\n",
    "\n",
    "\n",
    "# 线性正则\n",
    "from sklearn.linear_model import LinearRegression\n",
    "\n",
    "lr = LinearRegression()\n",
    "\n",
    "lr.fit(X_train, y_train)\n",
    "\n",
    "y_test_pred_lr = lr.predict(X_test)\n",
    "y_train_pred_lr = lr.predict(X_train)\n",
    "\n",
    "fs = pd.DataFrame({\"columns\":list(feat_names), \"coef\":list(lr.coef_.T)})\n",
    "fs.sort_values(by=['coef'],ascending=False)\n",
    "\n",
    "print ('The r2 score of LinearRegression on test is', r2_score(y_test, y_test_pred_lr))\n",
    "\n",
    "print ('The r2 score of LinearRegression on train is', r2_score(y_train, y_train_pred_lr))\n",
    "\n",
    "f, ax = plt.subplots(figsize=(7, 5))\n",
    "f.tight_layout()\n",
    "ax.hist(y_train - y_train_pred_lr, bins=40, label='Residuals Linear', color='b', alpha=.5)\n",
    "ax.set_title(\"Histogram of Residuals\")\n",
    "ax.legend(loc='best')\n",
    "\n",
    "\n",
    "\n",
    "#岭回归／L2正则\n",
    "\n",
    "from sklearn.linear_model import  RidgeCV\n",
    "\n",
    "alphas = [ 0.01, 0.1, 1, 10,100]\n",
    "\n",
    "ridge = RidgeCV(alphas=alphas, store_cv_values=True)\n",
    "\n",
    "ridge.fit(X_train, y_train)\n",
    "\n",
    "y_test_pred_ridge = ridge.predict(X_test)\n",
    "y_train_pred_ridge = ridge.predict(X_train)\n",
    "\n",
    "print ('The r2 score of RidgeCV on test is', r2_score(y_test, y_test_pred_ridge))\n",
    "print ('The r2 score of RidgeCV on train is', r2_score(y_train, y_train_pred_ridge))\n",
    "\n",
    "mse_mean = np.mean(ridge.cv_values_, axis = 0)\n",
    "plt.plot(np.log10(alphas), mse_mean.reshape(len(alphas),1))\n",
    "\n",
    "plt.xlabel('log(alpha)')\n",
    "plt.ylabel('mse')\n",
    "plt.show()\n",
    "\n",
    "print ('alpha is:', ridge.alpha_)\n",
    "\n",
    "\n",
    "# Lasso／L1正则\n",
    "\n",
    "from sklearn.linear_model import LassoCV\n",
    "\n",
    "lasso = LassoCV()\n",
    "\n",
    "lasso.fit(X_train, y_train)\n",
    "\n",
    "y_test_pred_lasso = lasso.predict(X_test)\n",
    "y_train_pred_lasso = lasso.predict(X_train)\n",
    "\n",
    "print ('The r2 score of LassoCV on test is', r2_score(y_test, y_test_pred_lasso))\n",
    "print ('The r2 score of LassoCV on train is', r2_score(y_train, y_train_pred_lasso))\n",
    "\n",
    "mses = np.mean(lasso.mse_path_, axis = 1)\n",
    "plt.plot(np.log10(lasso.alphas_), mses)\n",
    "\n",
    "plt.xlabel('log(alpha)')\n",
    "plt.ylabel('mse')\n",
    "plt.show()\n",
    "\n",
    "print ('alpha is:', lasso.alpha_)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "##题目五：代码中给出了岭回归（RidgeCV）和Lasso（LassoCV）超参数（alpha_）调优的过程，请结合两个最佳模型以及最小二乘线性回归模型的结果，给出什么场合应该用岭回归，什么场合用Lasso，什么场合用最小二乘。\n",
    "\n",
    "说明五：\n",
    "最小二乘（OLS）线性回归中，目标函数只考虑了模型对训练样本的拟合程度;\n",
    "L2正则使得线性回归系数收缩，模型稳定。当输入特征之间存在共线性时使用L2正则。\n",
    "L1正则也会收缩回归系数。当正则参数取合适值时，L1正则使得有些线性回归系数为0，得到稀疏模型。当输入特征多，有些特征与目标变量之间相关性很弱时， L1正则可能只选择强相关的特征，模型解释性好。\n",
    "\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}